복잡한 조건문이 있는 경우, 조건, then 부분, 그리고 else 부분에서 메소드를 추출하라.
| 변경 전 | 변경 후 | |
|---|---|---|
| {code} if(data.before(SUMMER_START) | data.after(SUMMER_END)) charge = quantity * _winterRate + _winterServiceCharer; else charge = quantity * _summerRate; {code} | {code} if(notSUmmer(date)) charge = winterCharge(quantity); else charge = summerCharge(quantity); {code} |
절차
같은 결과를 초래하는 일련의 조건 테스트가 있는 경우, 그것을 하나의 조건식으로 결합하여 뽑아내라.
| 변경 전 | 변경 후 |
|---|---|
| {code} doubul sdisabilityAmount(){ if(_seniority < 2) return 0; if(_monthsDisabled > 12) return 0; if(_isPatrTime) return 0; {code} | {code} double disabulityAmont(){ if(isNotEligableForDisability()) return 0; {code} |
절차
동일한 코드 조각이 조건문의 모든 분기 안에 있는 경우, 동일한 코드를 조건문 밖으로 옮겨라.
| 변경 전 | 변경 후 |
|---|---|
| {code} if(isSpecialDeal()){ total = price * 0.95; send(); }else{ total = price * 0.98; send(); } {code} | {code} if(isSpecialDeal()) total = price * 0.95; else total = price * 0.98; send(); {code} |
절차
일련의 boolean 식에서 컨트롤 플래그 역할을 하는 변수가 있는경우, break 또는 return 을 대신 사용하라.
| 변경 전 | 변경 후 |
|---|---|
| {code} void checkSecurity(String[] people){ boolean found = false; for(int i=0; i<people.length; i++){ if(!found){ if(people[i].equals("Don")){ sendAlert(); found = true; } if(people[i].equals("John")){ sendAlert(); found = true; } } } } {code} | {code} void checkSecurity(String[] people){ boolean found = false; for(int i=0; i<people.length; i++){ if(!found){ if(people[i].equals("Don")){ sendAlert(); break; } if(people[i].equals("John")){ sendAlert(); break; } } } } {code} |
| 변경 전 | 변경 후 |
|---|---|
| {code} void checkSecurity(String[] people){ boolean found = false; for(int i=0; i<people.length; i++){ if(!found){ if(people[i].equals("Don")){ sendAlert(); found = "Don"; } if(people[i].equals("John")){ sendAlert(); found = "John"; } } } } {code} | {code} void checkSecurity(String[] people){ boolean found = false; for(int i=0; i<people.length; i++){ if(!found){ if(people[i].equals("Don")){ sendAlert(); return "Don"; } if(people[i].equals("John")){ sendAlert(); return "John"; } } } } {code} |
절차
메소드가 정상적인 실행경로를 불명확하게 하는 조건 동작을 가지고 있는경우, 모든 특별한 경우에 대해서 보호절을 사용하라.
| 변경 전 | 변경 후 |
|---|---|
| {code} double getPayAmount(){ double result; if(_isDead) result = deadAmount(); else{ if(_isSeparated) result = seperatedAmount(); else{ if(_isRetired) result = retiredAmount(); else result = normalPayAmount(); } } return result; } {code} | {code} double getPayAmount(){ if(_isDead) return deadAmount(); if(_isseparated) return separatedAmount(); if(_isRetired) return retiredAmount(); return normalPayAmount(); } {code} |
절차
객체의 타입에 따른 다른 동작을 선택하는 조건문을 가지고 있는 경우, 조건문의 각 부분을 서브클래스에 있는 오버라이딩 메소드로 옮겨라.
그리고 원래 메소드를 abstrace로 만들어라.
double getSpeed(){
switch(_type){
case EUROPEAN:
return getBaseSpeed();
case AFRIACN:
return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
case NORWEGIAN_BLUE:
return(_isNailed) ? 0 : getBaseSpeed(_voltage);
}
}

절차
null 체크를 반복적으로 하고 있다면, null값을 null객체로 대체하라.
class NullCustomer extends Customer{
public boolean isNull(){
return true;
}
}
class Customer...
static Customer newNull(){
return new NullCustomer();
}
}
class Site...
Customer getCustomer(){
return(_customer == null) ?
Customer.newNull():
_customer;
}
class Site...
Customer getCustomer(){
return(_customer.isNull()) ?
Customer.newNull():
_customer;
}
//조건문을 제거함으로써 얻는 이익
String customerName;
if(customer.isNull()) customerName = "occupant";
else customerName = customer.getName();
//NullCustomer 클래스에 추가
class NullCustomer..
public String getName(){
return "occupant";
}
//위에 조건문을 없앤다.
String customerName = customer.getName();
코드의 한 부분이 프로그램의 상태에 대하여 어떤것을 가정하고 있으면, assertion을 써서 가정을 명시되게 만들어라.
| 변경 전 | 변경 후 | |
|---|---|---|
| {code} double getExpenseLimit(){ return(_expenseLimit != NULL_EXPENSE) ? _expenseLimit; _primaryProject.getMemberExpenseLimit(); } {code} | {code} double getExpenseLimit(){ Assert.isTrue(_expenseLimit != NULL_EXPENSE | _primaryProject != null); return (_expenseLimit != NULL_EXPENSE) ? _expenseLimit; _primaryProject.getMemberExpenseLimit(); } {code} |